package study.translation.parser;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

public class Lexem
{
    public static enum Type
    {
        IDENTIFIER( "Identifier", "[a-z]+" ),
        STRING( "String", "\"(.*?)\"" ),
        NUMBER( "Number", "(([0-9]+(\\.[0-9]+)?)i?)" ),

        // special symbols
        COLON( ":" ), SEMICOLON( ";" ), COMMA( "," ),
        PLUS( "+" ), MINUS( "-" ), STAR( "*" ), SLASH( "/" ),
        LBRACKET( "(" ), RBRACKET( ")" ),

        // reserved keywords
        PROGRAM,
        SUBROUTINE,
        ARGUMENTS,
        COMPLEX, DECIMAL,
        VARIABLES,
        RUN, WITH,
        PRINT,
        LOOP, FROM, TO,
        CHECK,
        TRUE, FALSE,
        AND, OR, NOT,
        EQ, LT, GT, GE, LE,
        RE, IM,
        END;

        private static Map<String, Type> nameMap = new HashMap<String, Type>();

        static
        {
            for( Type type : Type.values() )
            {
                nameMap.put( type.getName(), type );
            }
        }

        String name;

        Pattern pattern;

        Type( String name, String pattern )
        {
            this.name = name;
            this.pattern = Pattern.compile( pattern );
        }

        Type( String name )
        {
            this.name = name;
            this.pattern = Pattern.compile( Pattern.quote( name ) );
        }

        Type()
        {
            this.name = toString().toLowerCase();
            this.pattern = Pattern.compile( Pattern.quote( toString().toLowerCase() ) );
        }

        public String getName()
        {
            return name;
        }

        public Pattern getPattern()
        {
            return pattern;
        }

        public static Type byName( String name )
        {
            return nameMap.get( name );
        }
    }

    private Type type;

    private String contents;

    private FilePosition begin;

    private FilePosition end;

    public Lexem( Type type, String contents, FilePosition begin, FilePosition end )
    {
        this.type = type;
        this.contents = contents;
        this.begin = begin;
        this.end = end;
    }

    public Type getType()
    {
        return type;
    }

    public String getContents()
    {
        return contents;
    }

    public FilePosition getBegin()
    {
        return begin;
    }

    public FilePosition getEnd()
    {
        return end;
    }
}
